package shm;
/*
 * This is the main part of the program. Provides the framework of the user interface, and
 * the functions
 * The framework contains the following parts: 
 * (1) the main
 * (2) the parameter : Parameter()
 * (3) Online show: Oscilloscope()
 * (4) Offline show: 
 */
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import java.io.*;
import java.net.URL;
import java.util.prefs.*;

import javax.comm.*;
import javax.imageio.ImageIO;

import org.jfree.chart.*;

public class MainUI {
	
	public final static boolean DEBUG = false;

	//two tabs
	public static Window os;
	public static OfflineWindow offwin;
	public static Topology tp;
	
	// UI
	public static JButton btnStart, btnStop;
	public static JComboBox cbCOM, cbCmd;
	public static JTextField tfCmdParam;
	public static JTextArea taStatus;
	public static JScrollPane spStatus;
	
	// serial operation
	public static SerialPort serialport;
	public static InputStream in;
	public static OutputStream out;
	public static ReadSerialThread rs;
	
	// global preference
	public static Preferences pref = Preferences.userRoot().node("/com/shm");
	
	// public static File save_topology
	public static void main(String[] args) throws Exception {
		
		JFrame frame = new JFrame("SHM Application");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");

		tp = new Topology();
		Topology.topo.setVisible(false);

		offwin = new OfflineWindow();
		offwin.setup();

		os = new Window();
		os.setup();

		frame.setSize(900, 620);
		frame.getContentPane().setLayout(null);

		JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
		tabbedPane.setBounds(180, 50, 711, 543);
		frame.getContentPane().add(tabbedPane);
		
		// tab 3
		JPanel jpsa = new JPanel();
		jpsa.setLayout(null);
		jpsa.setBounds(152, 36, 572, 342);
		ChartPanel cpf = new ChartPanel(OfflineWindow.jfc);
		cpf.setBounds(0, 0, 705, 393);
		jpsa.add(cpf);
		
		JButton btnFFT3 = new JButton("FFT");
		btnFFT3.setBounds(50, 415, 100, 30);
		jpsa.add(btnFFT3);
		
		JButton btnCSD = new JButton("Power Spectral Density");
		btnCSD.setBounds(250, 415, 200, 30);
		jpsa.add(btnCSD);
		
		JButton btnWA = new JButton("Wavelet Analysis");
		btnWA.setBounds(550, 415, 130, 30);
		jpsa.add(btnWA);
		
		// Event
		btnFFT3.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				MatlabOP.selectFileAndCall("shmfft");
			}
		});
		
		btnCSD.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				MatlabOP.selectFileAndCall("shmpsd");
			}
		});
		
		btnWA.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				MatlabOP.selectFileAndCall("shmwa");
			}
		});
		
		// tab 4
		JPanel jpmi = new JPanel();
		jpmi.setLayout(null);
		jpmi.setBounds(152, 36, 572, 342);
		ChartPanel cpf2 = new ChartPanel(OfflineWindow.jfc);
		cpf2.setBounds(0, 0, 705, 393);
		jpmi.add(cpf2);
		
		JButton btnAR = new JButton("AR");
		btnAR.setBounds(50, 415, 100, 30);
		jpmi.add(btnAR);
		
		JButton btnSI = new JButton("Subspace Identification");
		btnSI.setBounds(350, 415, 180, 30);
		jpmi.add(btnSI);
		
		// Event
		btnAR.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				MatlabOP.selectFileAndCall("shmar");
			}
		});
		
		btnSI.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				MatlabOP.selectFileAndCall("shmsi");
			}
		});
		
		tabbedPane.addTab("Online", null, Window.main);
		tabbedPane.addTab("Offline", null, OfflineWindow.main);
		tabbedPane.addTab("Spectrum Analysis", null, jpsa);
		tabbedPane.addTab("Model Identification", null, jpmi);

		
		// Topology
		JButton btnTopology_1 = new JButton("Topology");
		btnTopology_1.setBounds(10, 50, 140, 30);
		btnTopology_1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				Topology.topo.setVisible(true);
			}
		});
		frame.getContentPane().add(btnTopology_1);
		
		
		// Battery
		JButton btnBattery = new JButton("Remaining Battery");
		btnBattery.setBounds(10, 90, 140, 30);
		frame.getContentPane().add(btnBattery);
		btnBattery.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				BatteryFrame bf = new BatteryFrame();
				bf.setVisible(true);
			}
		});
		
		// LOGO
		Image myPicture = null;
		try {
			ClassLoader cl = ClassLoader.getSystemClassLoader();
	    	URL iconURL = cl.getResource("shm/polyu.jpg");	
	    	myPicture = ImageIO.read(iconURL).getScaledInstance(288, 54, Image.SCALE_DEFAULT);
		} catch (IOException e) {
			e.printStackTrace();
		}
        JLabel picLabel = new JLabel(new ImageIcon( myPicture ));
        picLabel.setBounds(630, 1, 288, 54);
        frame.getContentPane().add( picLabel );
		
		btnStart = new JButton("Start");
		btnStop = new JButton("Stop");
		btnStart.setBounds(136, 3, 60, 26);
		frame.getContentPane().add(btnStart);
		btnStop.setEnabled(false);
		btnStop.setBounds(200, 3, 60, 26);
		frame.getContentPane().add(btnStop);

		btnStart.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String lastPath = MainUI.pref.get("lastPath", ".");
				
				JFileChooser jfc = new JFileChooser(lastPath);
				jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				jfc.setAcceptAllFileFilterUsed(false);
				
				{
					Logger.instance().start(lastPath);
					
					// OPEN COM port
					try {
						String portNum = MainUI.cbCOM.getSelectedItem().toString();
						CommPortIdentifier PortId = CommPortIdentifier.getPortIdentifier("COM" + portNum);
						serialport = (SerialPort) PortId.open("serial", 3000);
						serialport.setSerialPortParams(
								115200, 
								SerialPort.DATABITS_8, 
								1,
								SerialPort.PARITY_NONE);
						
						// save user selection
						pref.put("comPort", portNum);
						
						in = serialport.getInputStream();
						out = serialport.getOutputStream();

						rs = new ReadSerialThread(in);
						rs.start();
						//rs.nSeq = 1;
					} catch (Exception ex) {
						System.out.println("Open PORT ERROR");
						ex.printStackTrace();
					}
					
				MainUI.btnStart.setEnabled(false);
				MainUI.btnStop.setEnabled(true);
				}
			}
		});

		btnStop.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				// let the thread exit
				ReadSerialThread.state = -1;

				// wait to exit
				try {
					MainUI.rs.join(4000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
				
				// close port
				try {
					MainUI.in.close();
					MainUI.serialport.close();
					MainUI.serialport = null;
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				
				// close files
				Logger.instance().stop();
				btnStop.setEnabled(false);
				btnStart.setEnabled(true);
				
				MainUI.taStatus.setText("");
				
			}
		});


		JLabel lblCom = new JLabel("COM");
		lblCom.setBounds(12, 3, 46, 26);
		frame.getContentPane().add(lblCom);

		cbCOM = new JComboBox();
		cbCOM.setBounds(50, 3, 70, 26);
		frame.getContentPane().add(cbCOM);
		for(int i = 1; i <= 30; i++)
		{
			cbCOM.addItem(String.valueOf(i));
		}
		 
		String portNum = MainUI.pref.get("comPort", "1");
		cbCOM.setSelectedItem(portNum);

//		Hashtable<Integer, JLabel> xTable = new Hashtable<Integer, JLabel>();
//		for (int i = 0; i <= 8; i += 2) {
//			xTable.put(new Integer(i), new JLabel("" + (Graph.MIN_WIDTH << i)));
//		}
		
		JLabel lblCmd = new JLabel("Cmd");
		lblCmd.setBounds(5, 140, 45, 25);
		frame.getContentPane().add(lblCmd);
		
		cbCmd = new JComboBox();
		cbCmd.setBounds(35, 140, 130, 25);
		frame.getContentPane().add(cbCmd);
		String [] cmdStrings = {
				"Start Sample At",
				"Set Sample Rate",
				"Set Sample Time",
				"Stop",
				"Transfer",
				"Presample",
				"Realtime Data"
				};
		for (String s : cmdStrings){
			cbCmd.addItem(s);
		}
		
		JLabel lblParam = new JLabel("Param");
		lblParam.setBounds(5, 180, 45, 25);
		frame.getContentPane().add(lblParam);
		
		tfCmdParam = new JTextField("5");
		tfCmdParam.setBounds(50, 180, 100, 25);
		frame.getContentPane().add(tfCmdParam);
		
		JButton btCmd = new JButton("Send Cmd");
		btCmd.setBounds(20, 220, 100, 25);
		frame.getContentPane().add(btCmd);
		
		btCmd.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (MainUI.serialport == null)
					return;
				
				// Get the parameter;
				int param = 0;
				byte cmd = 0;
				
				try {
					cmd = (byte) cbCmd.getSelectedIndex();
					cmd++;
					param = Integer.parseInt(tfCmdParam.getText());
					
					MainUI.SendCommand(cmd, param);
				}
				catch(Exception ex) {
					ex.printStackTrace();
				}
				
			}
		});
		
		taStatus = new JTextArea("Status:");
		taStatus.setEditable(false);
		taStatus.setLineWrap(true);
		
		spStatus = new JScrollPane(taStatus);
		spStatus.setBounds(1, 250, 180, 320);
		frame.getContentPane().add(spStatus);
		
		if(DEBUG)
			SimulatedSerialThread.showTestButton(frame);
		
		frame.setVisible(true);
	}
	

	/* send command to com port.
	 0  1  2  3  4  5  6  7
	FF 06 03 00 00 04 B0 B7  20����
	����������8 bits ������ + 32bits��������
	
	a.	Start sample at
	b.	Set sampling rate
	c.	Set sampling time: 
	d stop:
	 */
	public static void SendCommand(byte cmdId, int param)
	{
		byte[] buf = new byte[8];
		buf[0] = (byte) 0xff;	// signature
		buf[1] = 6;				// length
		buf[2] = cmdId;			// id
		
		// param
		buf[3] = (byte)(param >>> 24);
		buf[4] = (byte)(param >>> 16);
		buf[5] = (byte)(param >>> 8);
		buf[6] = (byte)(param);
		
		// calculate checksum
		short checksum = 0;
		for(int i = 2; i <= 6; i++){
			checksum += buf[i];
		}
		
		buf[7] = (byte) checksum;
		try {
			out.write(buf);
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
